package com.powernode.task;

import com.powernode.constant.Constants;
import com.powernode.entity.Goods;
import com.powernode.service.GoodsService;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * 商品定时任务类
 * 负责缓存预热操作，将MySQL中的商品信息定期同步到Redis缓存
 * 解决秒杀场景下数据库访问压力大的问题，提高系统响应速度
 */
@EnableScheduling // 启用定时任务功能，允许使用@Scheduled注解定义定时任务
@Component // 标记为Spring组件，使其能够被Spring容器扫描并管理
public class GoodsTask {
    @Resource
    private GoodsService goodsService; // 注入商品服务，用于从数据库查询商品信息

    @Resource
    private RedisTemplate redisTemplate; // 注入Redis模板，用于操作Redis缓存（存储商品对象）

    @Resource
    private StringRedisTemplate stringRedisTemplate; // 注入字符串Redis模板，用于操作Redis缓存（存储商品库存）

    /**
     * 定时任务：商品信息缓存预热
     * 每3秒执行一次，将MySQL中的商品信息同步到Redis缓存
     * 解决秒杀高并发场景下的缓存穿透和数据库访问压力问题
     *
     * @Scheduled注解说明：
     * cron表达式"0/3 * * * * *"表示从0秒开始，每3秒执行一次
     * 格式：[秒] [分] [时] [日] [月] [周]，*表示任意值，0/3表示从0开始每隔3个单位
     */
    @Scheduled(cron = "0/3 * * * * *")
    public void initGoodsToCache() {
        // 1. 从数据库查询所有商品信息
        List<Goods> goodsList = goodsService.list();

        // 2. 遍历商品列表，将商品信息存入Redis缓存
        goodsList.forEach(goods -> {
            // 2.1 存储商品完整信息到Redis
            // 使用RedisTemplate的opsForValue()方法操作字符串类型数据
            // 键格式：Constants.REDIS_GOODS + 商品ID（例如：goods:1001）
            // 值：商品对象（会被序列化为JSON格式存储）
            redisTemplate.opsForValue().set(Constants.REDIS_GOODS + goods.getId(), goods);

            // 2.2 存储商品库存到Redis
            // 使用StringRedisTemplate的setIfAbsent方法：若key不存在则存入，存在则不操作
            // 防止重复初始化覆盖已有库存数据（例如秒杀过程中已减少的库存）
            // 键格式：Constants.REDIS_STORE + 商品ID（例如：store:1001）
            // 值：商品库存数量（转换为字符串存储）
            stringRedisTemplate.opsForValue().setIfAbsent(
                    Constants.REDIS_STORE + goods.getId(),
                    goods.getStore().toString()
            );
        });
    }
}
